#pragma once

#include <uapi/linux/input-event-codes.h>




#define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"

#define SONYPI_TYPE1_OFFSET 0x04
#define SONYPI_TYPE2_OFFSET 0x12
#define SONYPI_TYPE3_OFFSET 0x12

#define SONYPI_DEVICE_TYPE1 0x00000001
#define SONYPI_DEVICE_TYPE2 0x00000002
#define SONYPI_DEVICE_TYPE3 0x00000004


/***************
*     INPUT    *
***************/

struct input_dev* vgnux_input_device;

static int vgnux_input_keycode_map[] = {
	KEY_PROG1,
	KEY_PROG2,
	KEY_PROG3,
	KEY_CAMERA,
	KEY_WLAN,
	KEY_WWAN,
	KEY_DISPLAY_OFF,
	
	KEY_RESERVED//list terminator
};

/************************
*    Platform Device    *
************************/


static struct platform_driver sony_pf_driver = {
	.driver = {
		   .name = KBUILD_MODNAME,
		   }
};
static struct platform_device* sony_pf_device;


/***************
*    CAMERA    *
***************/
//camera tests and poweron/poweroff
#define SONYPI_CAMERA_PICTURE      5
#define SONYPI_CAMERA_CONTROL     0x10

#define SONYPI_CAMERA_BRIGHTNESS  0
#define SONYPI_CAMERA_CONTRAST    1
#define SONYPI_CAMERA_HUE         2
#define SONYPI_CAMERA_COLOR       3
#define SONYPI_CAMERA_SHARPNESS   4

#define SONYPI_CAMERA_EXPOSURE_MASK      0xC
#define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
#define SONYPI_CAMERA_PICTURE_MODE_MASK  0x30
#define SONYPI_CAMERA_MUTE_MASK          0x40

//the rest don't need a loop until not 0xff
#define SONYPI_CAMERA_AGC          6
#define SONYPI_CAMERA_AGC_MASK     0x30
#define SONYPI_CAMERA_SHUTTER_MASK 0x7

#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
#define SONYPI_CAMERA_CONTROL          0x10

#define SONYPI_CAMERA_STATUS            7
#define SONYPI_CAMERA_STATUS_READY      0x2
#define SONYPI_CAMERA_STATUS_POSITION   0x4

#define SONYPI_DIRECTION_BACKWARDS 0x4

#define SONYPI_CAMERA_REVISION    8
#define SONYPI_CAMERA_ROMVERSION  9


//used only for communication between v4l and sony-laptop
#define SONY_PIC_COMMAND_GETCAMERA           1	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERA           2
#define SONY_PIC_COMMAND_GETCAMERABRIGHTNESS 3	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERABRIGHTNESS 4
#define SONY_PIC_COMMAND_GETCAMERACONTRAST   5	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACONTRAST   6
#define SONY_PIC_COMMAND_GETCAMERAHUE        7	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAHUE        8
#define SONY_PIC_COMMAND_GETCAMERACOLOR      9	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACOLOR      10
#define SONY_PIC_COMMAND_GETCAMERASHARPNESS  11	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERASHARPNESS  12
#define SONY_PIC_COMMAND_GETCAMERAPICTURE    13	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAPICTURE    14
#define SONY_PIC_COMMAND_GETCAMERAAGC        15	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAAGC        16
#define SONY_PIC_COMMAND_GETCAMERADIRECTION  17	/* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAROMVERSION 18	/* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAREVISION   19	/* obsolete */



/****************/

struct sony_pic_irq {
	struct acpi_resource_irq irq;
	struct list_head         list;
};


struct sony_pic_ioport {
	struct acpi_resource_io io1;
	struct acpi_resource_io io2;
	struct list_head        list;
};

struct sony_pic_dev {
	struct acpi_device*             acpi_dev;
	struct sony_pic_irq*            cur_irq;
	struct sony_pic_ioport*         cur_ioport;
	struct list_head                interrupts;
	struct list_head                ioports;
	struct mutex                    lock;
	const struct sonypi_eventtypes* event_types;
	int                             (*handle_irq)(const u8, const u8);
	int                             model;
	u16                             evport_offset;
	u8                              camera_power;
	u8                              bluetooth_power;
	u8                              wwan_power;
};

static struct sony_pic_dev spic_dev = {
	.interrupts = LIST_HEAD_INIT(spic_dev.interrupts),
	.ioports    = LIST_HEAD_INIT(spic_dev.ioports),
};

/**************************
*         EVENTS          *
**************************/

struct sonypi_event {
	u8  data;
	int key;
};

struct sonypi_eventtypes {
	u8                         data;
	const struct sonypi_event* events;
};

/***VGN-UX DB***/

static const struct sonypi_event vgnux_buttons[] = {
	{ 0x01, KEY_PROG1  },//menu
	{ 0x10, KEY_PROG2  },//zoomin
	{ 0x20, KEY_PROG3  },//zoomout
	{ 0x40, KEY_CAMERA },//cam
	{ 0,    0          }
};

static const struct sonypi_event vgnux_fnkeys[] = {
	{ 0x11, KEY_WWAN },//fn+f
	{ 0x1f, 0        },//fn release
	{ 0x36, 0        },//fn only
	{ 0,    0        }
};

static const struct sonypi_event vgnux_power[] = {
	{ 0x56, 0               },//dock in
	{ 0x57, 0               },//dock out
	{ 0x59, KEY_WLAN        },//wlan on
	{ 0x5a, KEY_WLAN        },//wlan off
	{ 0xb9, KEY_DISPLAY_OFF },//hold
	{ 0,    0 }
};

static const struct sonypi_event vgnux_battery[] = {
	{ 0x20, 0 },//insert
	{ 0x30, 0 },//remove
	{ 0,    0 }
};

static const struct sonypi_eventtypes vgnux_events[] = {
	{ 0x05, vgnux_buttons },
	{ 0x21, vgnux_fnkeys  },
	{ 0x31, vgnux_power   },
	{ 0x41, vgnux_battery },
	{ 0,    0             }
};

static const struct sonypi_eventtypes dummy_events[] = {
	{ 0, 0 }
};


/***********************
*    DRIVER STRUCTS    *
***********************/
static int sony_pic_add( struct acpi_device* device );
static int sony_pic_remove( struct acpi_device* device );

#ifdef CONFIG_PM_SLEEP
static int sony_pic_suspend( struct device* dev );
static int sony_pic_resume( struct device* dev );
#endif

static SIMPLE_DEV_PM_OPS( sony_pic_pm, sony_pic_suspend, sony_pic_resume );

static const struct acpi_device_id sony_pic_device_ids[] = {
	{ "SNY6001", 0 },
	{ "",        0 },
};

static struct acpi_driver sony_pic_driver = {
	.name  = SONY_PIC_DRIVER_NAME,
	.class = "sony-pic",
	.ids   = sony_pic_device_ids,
	.owner = THIS_MODULE,
	.ops = {
		.add    = sony_pic_add,
		.remove = sony_pic_remove,
		},
	.drv.pm = &sony_pic_pm,
};

const struct dmi_system_id sonypi_dmi_table[] __initconst = {
	{
		.ident = "Sony Vaio",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
		},
	},
	{ }
};

